
from fastapi import APIRouter, Depends
from schemas.common import RETURN, ListRequest, Filter
from sqlalchemy.orm import load_only
from database.mysql import get_async_session
from sqlmodel.ext.asyncio.session import AsyncSession
from sqlalchemy.future import select
from sqlalchemy import delete
from starlette.responses import StreamingResponse
from typing import Optional, List

from models.Base import StatusTypeEnum
import models.admin.system.Role as RoleModel
import models.admin.system.Menu as MenuModel
import models.admin.system.Admin as AdminModel
import models.admin.system.Link as LinkModel
from server.Base import BaseServer
from routers.admin.common import convert_filter_values
from utils import util

from core.Depend import has_permission
#添加角色
router = APIRouter(prefix="/role" , tags=["角色管理"])
@router.post("/add",summary="角色添加")
async def add(role: RoleModel.create_role, menuIds: list[int] = [], session: AsyncSession = Depends(get_async_session),user: AdminModel.redis_admin = Depends(has_permission("system_admin_role_add"))):
    # code 不能重复
    statement = select(RoleModel.Role).where(RoleModel.Role.code == role.code)
    result = await session.exec(statement)
    isHas:RoleModel.Role = result.scalars().first()
    if isHas:
        return RETURN.fail("角色编码已存在")
    
    try:
        role = RoleModel.Role(**role.model_dump())
        session.add(role)
        # 获取到插入的id
        await session.flush()
        # 再添加新的权限
        add_data = [RoleModel.Role_Menu_Link(role_id=role.id, menu_id=menuId) for menuId in menuIds]
        session.add_all(add_data)
        await session.commit()
        return RETURN.success("添加成功")
    except Exception as e:
        await session.rollback()
        return RETURN.fail("添加失败")

#删除角色
@router.delete("/delete",summary="角色删除")
async def role_delete(id: int,  session: AsyncSession = Depends(get_async_session),user: AdminModel.redis_admin = Depends(has_permission("system_admin_role_del"))):
    # 一并删除角色权限
    try:
        if id == 1:
            return RETURN.fail("超级管理员角色不允许删除")
        # 判断该角色是否已经分配给用户
        statement = select(AdminModel.Admin).where(LinkModel.Admin_Role_Link.role_id == id)
        result = await session.exec(statement)
        isHas:AdminModel.Admin = result.scalars().first()
        if isHas:
            return RETURN.fail("该角色已经分配给用户，无法删除")
        
        # 判断该角色是否有子角色，如果有子角色，不允许删除
        statement = select(RoleModel.Role).where(RoleModel.Role.parent_id == id)
        result = await session.exec(statement)
        isHas:RoleModel.Role = result.scalars().first()
        if isHas:
            return RETURN.fail("该角色有子角色，无法删除，请先删除子角色")

        delete_statement = delete(RoleModel.Role_Menu_Link).where(RoleModel.Role_Menu_Link.role_id == id)
        await session.exec(delete_statement)

        delete_statement = delete(RoleModel.Role).where(RoleModel.Role.id == id)
        await session.exec(delete_statement)

        await session.commit()
        return RETURN.success("删除成功")
    except Exception as e:
        await session.rollback()
        return RETURN.fail(f"删除失败: {str(e)}")


#修改角色
@router.put("/update",summary="角色修改")
async def update(role: RoleModel.edit_role, menuIds: list[int] = [], session: AsyncSession = Depends(get_async_session),user: AdminModel.redis_admin = Depends(has_permission("system_admin_role_edit"))):
    statement = select(RoleModel.Role).where(RoleModel.Role.code == role.code).where(RoleModel.Role.id != role.id)
    result = await session.exec(statement)
    existing_role= result.scalars().first()
    if existing_role :
        return RETURN.fail("角色编码已存在")
    try:
        # 查询要更新的角色
        statement = select(RoleModel.Role).where(RoleModel.Role.id == role.id)
        result = await session.exec(statement)
        Role = result.scalars().first()

        if not Role:
            return RETURN.fail("角色不存在")
        # 根据id修改
        Role.name = role.name
        Role.code = role.code
        Role.remark = role.remark
        Role.status = role.status
        Role.parent_id = role.parent_id
    
        # 先删除原有的权限
        delete_statement = delete(RoleModel.Role_Menu_Link).where(RoleModel.Role_Menu_Link.role_id == role.id)
        await session.exec(delete_statement)
        # 再添加新的权限
        add_data = [RoleModel.Role_Menu_Link(role_id=role.id, menu_id=menuId) for menuId in menuIds]
        session.add_all(add_data)
        await session.commit()
        return RETURN.success("修改成功")
    except Exception as e:
        await session.rollback()
        return RETURN.fail(f"角色修改失败: {str(e)}")

# 修改角色状态
@router.put("/status",summary="角色状态")
async def status(id: int, status: int, user: AdminModel.redis_admin = Depends(has_permission("system_admin_role_status"))):
    await BaseServer(RoleModel.Role).change_status(id, status)
    return RETURN.success("修改成功")

#查询角色
@router.post("/list",summary="角色列表")
async def list(request:ListRequest,user: AdminModel.redis_admin = Depends(has_permission("system_admin_role_list"))):
    fields = ["id", "name","code","status","createtime","updatetime","remark","parent_id"]
    conversion_map = {
        "status": StatusTypeEnum,
    }
    request.filter = await convert_filter_values(conversion_map,request.filter)
    result = await BaseServer(RoleModel.Role).list(request, fields=fields)
    return RETURN.success("查询成功",result)

# 所有角色
@router.post("/all",summary="所有角色")
async def all(filters: List[Filter] = [], user: AdminModel.redis_admin = Depends(has_permission("system_admin_role_all"))):
    fields = ["id", "name","code","status","createtime","remark","parent_id"]
    conversion_map = {
        "status": StatusTypeEnum,
    }
    filters = await convert_filter_values(conversion_map,filters)
    result = await BaseServer(RoleModel.Role).all(filters=filters,fields=fields)
    return RETURN.success("查询成功",result)

#查询角色信息
@router.get("/info",summary="角色信息")
async def info(id: int,user: AdminModel.redis_admin = Depends(has_permission("system_admin_role_info"))):
    fields = ["id", "name","code","status","createtime","updatetime","remark"]
    result = await BaseServer(RoleModel.Role).get(id, fields=fields)
    return RETURN.success("查询成功",result)
   
#分配权限
@router.post("/assign",summary="角色分配权限")
async def assign(assignParams:RoleModel.assignParams, session: AsyncSession = Depends(get_async_session),user: AdminModel.redis_admin = Depends(has_permission("system_admin_role_assign"))):
     # 先删除原有的权限
    delete_statement = delete(RoleModel.Role_Menu_Link).where(RoleModel.Role_Menu_Link.role_id == assignParams.id)
    await session.exec(delete_statement)
    await session.commit()
    # 再添加新的权限
    add_data = [RoleModel.Role_Menu_Link(role_id=assignParams.id, menu_id=menuId) for menuId in assignParams.menuIds]
    session.add_all(add_data)
    await session.commit()
    return RETURN.success("分配成功")

    
# 查询角色权限
@router.get("/menu",summary="角色权限")
async def menu(id: int, session: AsyncSession = Depends(get_async_session),user: AdminModel.redis_admin = Depends(has_permission("system_admin_role_menu"))):
    # TODO:如果id为1，返回所有权限的id
    if id == 1:
        fields = [MenuModel.Menu.id]
        statement = select(MenuModel.Menu).options(load_only(*fields))
        result = await session.exec(statement)
        datas = result.scalars().all()
        ids = [item.id for item in datas]
        return RETURN.success("查询成功",ids)
        
    statement = select(RoleModel.Role_Menu_Link.menu_id).where(RoleModel.Role_Menu_Link.role_id == id)
    result = await session.exec(statement)
    datas = result.scalars().all()
    return RETURN.success("查询成功",datas)

# 查询所有角色权限
@router.get("/role_menu",summary="所有角色权限")
async def role_menu(id:Optional[int] = 1, session: AsyncSession = Depends(get_async_session),user: AdminModel.redis_admin = Depends(has_permission("system_admin_roles_menu"))):
    fields = [
        MenuModel.Menu.parent_id,
        MenuModel.Menu.id,
        MenuModel.Menu.title,
        MenuModel.Menu.menu_type
    ]
    # 根据角色id查询角色权限
   
    if id == 1:
        statement = select(MenuModel.Menu).options(load_only(*fields))
        result = await session.exec(statement)
        datas = result.scalars().all()
    else:
        statement = select(RoleModel.Role_Menu_Link.menu_id).where(RoleModel.Role_Menu_Link.role_id == id)
        result = await session.exec(statement)
        menu_datas = result.scalars().all()
        menu_ids = [item for item in menu_datas]
        statement = select(MenuModel.Menu).where(MenuModel.Menu.id.in_(menu_ids)).options(load_only(*fields))
        result = await session.exec(statement)
        datas = result.scalars().all()
    return RETURN.success("查询成功", datas)

# 导出角色
@router.post("/export",summary="导出角色")
async def export(request:ListRequest,user: AdminModel.redis_admin = Depends(has_permission("system_admin_role_export"))):
    data, headers = await BaseServer(RoleModel.Role).export(request.filter,request.fields)
    return StreamingResponse(util.generate_large_csv_from_sqlmodel(data), headers=headers)
